<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="hOl7b" id="hOl7b"><span data-lake-id="u29526414" id="u29526414">典型回答</span></h1>
  <h2 data-lake-id="esgQV" id="esgQV"><span data-lake-id="u28c5cd5e" id="u28c5cd5e">volatile和可见性</span></h2>
  <p data-lake-id="u314b0540" id="u314b0540"><br></p>
  <p data-lake-id="uc1b8271b" id="uc1b8271b"><span data-lake-id="u4f81b8bf" id="u4f81b8bf">对于volatile变量，当对volatile变量进行写操作的时候，JVM会向处理器发送一条lock前缀的指令，将这个缓存中的变量回写到系统主存中。</span></p>
  <p data-lake-id="uedcbad2d" id="uedcbad2d"><span data-lake-id="uc9d21c44" id="uc9d21c44">​</span><br></p>
  <p data-lake-id="u0f82cf35" id="u0f82cf35"><span data-lake-id="u6f0803b1" id="u6f0803b1">所以，如果一个变量被volatile所修饰的话，在每次数据变化之后，其值都会被强制刷入主存。而其他处理器的缓存由于遵守了缓存一致性协议，也会把这个变量的值从主存加载到自己的缓存中。这就保证了一个volatile在并发编程中，其值在多个缓存中是可见的。</span></p>
  <p data-lake-id="uefde9090" id="uefde9090"><span data-lake-id="u09cf3acd" id="u09cf3acd">​</span><br></p>
  <p data-lake-id="u41a8f23e" id="u41a8f23e"><span data-lake-id="u8d7ca031" id="u8d7ca031">​</span><br></p>
  <h2 data-lake-id="eGsYf" id="eGsYf"><span data-lake-id="u46cdd6c2" id="u46cdd6c2">volatile和有序性</span></h2>
  <p data-lake-id="u56cb00ab" id="u56cb00ab"><br></p>
  <p data-lake-id="uddacf587" id="uddacf587"><span data-lake-id="u56008ca4" id="u56008ca4">volatile除了可以保证数据的可见性之外，还有一个强大的功能，那就是他可以禁止指令重排优化等。</span></p>
  <p data-lake-id="ube8b70ea" id="ube8b70ea"><span data-lake-id="u40a23760" id="u40a23760">​</span><br></p>
  <p data-lake-id="u2da390bf" id="u2da390bf"><span data-lake-id="u362b4017" id="u362b4017">普通的变量仅仅会保证在该方法的执行过程中所依赖的赋值结果的地方都能获得正确的结果，而不能保证变量的赋值操作的顺序与程序代码中的执行顺序一致。</span></p>
  <p data-lake-id="u3fb06496" id="u3fb06496"><span data-lake-id="ua345a316" id="ua345a316">​</span><br></p>
  <p data-lake-id="ufe3cd19c" id="ufe3cd19c"><strong><span data-lake-id="u4af2fd84" id="u4af2fd84">volatile是通过内存屏障来禁止指令重排的</span></strong><span data-lake-id="ud7880dc1" id="ud7880dc1">，这就保证了代码的程序会严格按照代码的先后顺序执行。这就保证了有序性。被volatile修饰的变量的操作，会严格按照代码顺序执行，load-&gt;add-&gt;save 的执行顺序就是：load、add、save。</span></p>
  <p data-lake-id="uc5a484d6" id="uc5a484d6"><br></p>
  <p data-lake-id="u8c50d874" id="u8c50d874"><span data-lake-id="u95c39217" id="u95c39217">如经典的双重校验锁必须加volatile的问题，就是因为volatile加了内存屏障。</span></p>
  <p data-lake-id="u58b9b313" id="u58b9b313"><span data-lake-id="u951009e2" id="u951009e2">​</span><br></p>
  <p data-lake-id="ufb6ae71b" id="ufb6ae71b"><span data-lake-id="u3ce5c861" id="u3ce5c861">​</span><br></p>
  <h1 data-lake-id="uI7EM" id="uI7EM"><span data-lake-id="u6a7ce222" id="u6a7ce222">扩展知识</span></h1>
  <h2 data-lake-id="rNo8M" id="rNo8M"><span data-lake-id="u119dbc01" id="u119dbc01">内存屏障</span></h2>
  <p data-lake-id="u0b90ef9f" id="u0b90ef9f"><br></p>
 </body>
</html>